package com.canaan.business.controller.pc.api.erp;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.canaan.business.common.enums.inOutStock.InOrderStatusEnum;
import com.canaan.business.domain.basic.ErpProduct;
import com.canaan.business.domain.bill.*;
import com.canaan.business.domain.vo.*;
import com.canaan.business.service.basic.IErpProductService;
import com.canaan.business.service.bill.*;
import com.canaan.common.annotation.ApiInterfaceLog;
import com.canaan.common.core.controller.BaseController;
import com.canaan.common.core.domain.AjaxResult;
import com.canaan.common.encrypt.AesCryptorUtils;
import com.canaan.common.encrypt.ApiResult;
import com.canaan.common.encrypt.ResultDTO;
import com.canaan.common.utils.DateUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Api(tags = "入库")
@RestController
@RequestMapping("")
@Slf4j
public class InStockController extends BaseController {
    @Resource
    IReceiveProductBillService receiveProductBillService;
    @Resource
    IReceiveProductBillDetailService receiveProductBillDetailService;
    @Resource
    IAdjustInBillService adjustInBillService;
    @Resource
    IAdjustInBillDetailService adjustInBillDetailService;
    @Resource
    IModulationInBillService modulationInBillService;
    @Resource
    IModulationInBillDetailService modulationInBillDetailService;

    @Resource
    IErpProductService productService;

    @Resource
    HttpCommonReq commonReq;

    /**
     * 出库创建
     */
    @ApiOperation(value = "入库创建(EDI)")
    @ApiInterfaceLog(title = "入库创建(EDI)")
    @PostMapping("/edi/inStock/ediCreate")
    public String ediCreate(HttpServletRequest request) {
        try {
            String requirementOrderReqJsonStr = commonReq.getCommonReq(request).getData();
            log.info("入库创建(EDI)入参:{}", requirementOrderReqJsonStr);
            InstockCreateVo instockCreateVo = JSONUtil.toBean(requirementOrderReqJsonStr, InstockCreateVo.class);
            String result = handleInStockCreate(instockCreateVo);
            log .info("入库创建(EDI)出参:{}", JSONUtil.toJsonStr(AjaxResult.success()));
            return buildResult(true, result);
        } catch (Exception e) {
            log.error("创建入库需求单异常,msg:{}", e.getMessage(), e);
            return buildResult(false, e.getMessage());
        }
    }
    /**
     * 入库取消
     */
    @ApiOperation(value = "入库取消")
    @ApiInterfaceLog(title = "入库取消")
    @PostMapping("/edi/inStock/ediCancel")
    public String cancel(HttpServletRequest request) {
        //TODO  采购⼊库单 DIPI 1    对应采购收货单   表名 wms_receive_product_bill wms_receive_product_bill_detail
        // 只有采购入库才会取消订单,需要判断单据当前状态,如果已入库,则不允许取消
        try {
            String jsonstr = commonReq.getCommonReq(request).getData();
            InStockCancelVo inStockCancelVo = JSONUtil.toBean(jsonstr, InStockCancelVo.class);

            ReceiveProductBill productBill = receiveProductBillService.selectReceiveProductBillByNo(inStockCancelVo.getBizNo());
            if (productBill == null) {
                throw new Exception(String.format("不存在%s采购收货单", inStockCancelVo.getBizNo()));
            }
            if (productBill.getStatus().equals(InOrderStatusEnum.NEW.getCode())) {
                productBill.setStatus(InOrderStatusEnum.CANCEL.getCode());
                receiveProductBillService.updateReceiveProductBill(productBill);
            } else {
                throw new Exception(String.format("%s采购收货单状态不是新建,不可以取消", inStockCancelVo.getBizNo()));
            }
            return buildResult(true, null);
        } catch (Exception e) {
            log.error("取消采购收货单异常,msg:{}", e.getMessage(), e);
            return buildResult(false, e.getMessage());
        }
    }
    /**
     * 出库创建
     */
    @ApiOperation(value = "入库创建")
    @ApiInterfaceLog(title = "入库创建")
    @PostMapping("/erp/inStock/create")
    public AjaxResult wmsCreate(@RequestBody InstockCreateVo instockCreateVo) {
        handleInStockCreate(instockCreateVo);
        return success();
    }

    /**
     * 入库回调
     */
    @ApiOperation(value = "入库回调")
    @ApiInterfaceLog(title = "入库回调")
    @PostMapping("/erp/inStock/callback")
    public AjaxResult callback(@RequestBody InStockCallbackVo inStockCallbackVo) {
        return success();
    }

    @ApiOperation(value = "入库取消")
    @ApiInterfaceLog(title="入库取消")
    @PostMapping("/erp/inStock/cancel")
    public AjaxResult cancel(@RequestBody InStockCancelVo inStockCancelVo) {
        try {
            //TODO  采购⼊库单 DIPI 1    对应采购收货单   表名 wms_receive_product_bill wms_receive_product_bill_detail
            // 只有采购入库才会取消订单,需要判断单据当前状态,如果已入库,则不允许取消
            ReceiveProductBill productBill=receiveProductBillService.selectReceiveProductBillByNo(inStockCancelVo.getBizNo());
            if (productBill == null) {
                throw new Exception(String.format("不存在%s采购收货单", inStockCancelVo.getBizNo()));
            }
            if (productBill.getStatus().equals(InOrderStatusEnum.NEW.getCode())) {
                productBill.setStatus(InOrderStatusEnum.CANCEL.getCode());
                receiveProductBillService.updateReceiveProductBill(productBill);
            } else {
                throw new Exception(String.format("%s采购收货单状态不是新建,不可以取消", inStockCancelVo.getBizNo()));
            }
            return AjaxResult.success();
        } catch (Exception e) {
            log.error("取消采购收货单异常,msg:{}", e.getMessage(), e);
            return AjaxResult.error(e.getMessage());
        }
    }


    /**
     * 处理入库创建
     *
     * @param instockCreateVo 入库创建对象
     * @return
     */
    @Transactional
    public String handleInStockCreate(InstockCreateVo instockCreateVo) {
        //TODO  采购⼊库单 DIPI 11    对应采购收货单   表名 wms_receive_product_bill wms_receive_product_bill_detail
        //      取消发货单 DIPI 31    不对应单据表,所有单据的取消都需要调用此接口  WMS需要判断是否已经在执行中,如果在执行中,则不允许取消
        //      采购退供 DORS 23      对应入库退货单   wms_purchase_return_bill wms_purchase_return_bill_detail
        //      调拨单⼊库单 DITRS 14  对应调拨入库单   wms_adjust_in_bill  wms_adjust_in_bill_detail
        //      调拨单出库单 DOTRS 24  对应调拨出库单   wms_adjust_out_bill wms_adjust_out_bill_detail
        //      出库调整单 DOWOO 22    不对应单据,可以新增单据表保存, 仅仅是调整出库数量
        //      ⼊库调整单 DIWOI 15    不对应单据,可以新增单据表保存, 仅仅是调整入库数量
        String result = "未找到此类型单据";
        boolean isSuccess = true;
        switch (instockCreateVo.getBusinessType()) {     //根据业务类型调用对应接口
            case 11:
                handleReceiveProductBill(instockCreateVo);
                result = "采购收货单创建成功";
                break;
            case 14:
                handleAdjustInBill(instockCreateVo);
                result = "调拨入库单创建成功";
                break;
            case 15:
                handleModulationInBill(instockCreateVo);
                result = "入库调整单创建成功";
                break;
            default:
                log.error("入库业务类型错误,业务类型:{}", instockCreateVo.getBusinessType());
                break;
        }
        if (!isSuccess) {
            throw new RuntimeException("入库业务类型错误,业务类型:" + instockCreateVo.getBusinessType());
        }
        return result;
    }

    /**
     * 采购入库单
     *
     * @param instockCreateVo 入库创建
     */
    private void handleReceiveProductBill(InstockCreateVo instockCreateVo) {
        //采购⼊库单
        //TODO 调用采购收货单创建接口
        ReceiveProductBillDetail bill = receiveProductBillDetailService.selectReceiveProductBillDetailByNo(instockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", instockCreateVo.getBizNo());
            return;
        }
        //主表入库
        ReceiveProductBill receiveProductBill = new ReceiveProductBill();
        receiveProductBill.setNo(instockCreateVo.getBizNo());
        receiveProductBill.setStockCode(instockCreateVo.getStockCode());
        receiveProductBill.setOwner(instockCreateVo.getOwner());
        receiveProductBill.setStockStatus(instockCreateVo.getStockStatus().toString());
        receiveProductBill.setShortMatch(instockCreateVo.getShortMatch().toString());
        receiveProductBill.setSplit(instockCreateVo.getIsSplit().toString());
        receiveProductBill.setArrivalDate(DateUtils.parseDate(instockCreateVo.getArrivalDate()));
        receiveProductBill.setRemark(instockCreateVo.getRemark());
        receiveProductBill.setCheckTotalQty(0l);
        receiveProductBill.setStatus(InOrderStatusEnum.NEW.getCode());
        Long total = 0l;
        //子表入库
        for (GoodsVo detail : instockCreateVo.getGoodDetails()) {
            ReceiveProductBillDetail receiveProductBillDetail = new ReceiveProductBillDetail();
            receiveProductBillDetail.setBillNo(instockCreateVo.getBizNo());
            receiveProductBillDetail.setProductNo(detail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(detail.getCode());
            if (product != null) {
                receiveProductBillDetail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(detail.getNum());
            receiveProductBillDetail.setQty(num);
            receiveProductBillDetail.setReceivedQty(0l);
            receiveProductBillDetail.setProductUnit(detail.getUnit());
            receiveProductBillDetail.setBatchNo(detail.getBatchNo());
            receiveProductBillDetail.setCreateBy("ERP");
            receiveProductBillDetail.setStockStatus(instockCreateVo.getStockStatus()+"");
            total += num;
            receiveProductBillDetailService.insertReceiveProductBillDetail(receiveProductBillDetail);
        }
        receiveProductBill.setTotalQty(total);
        receiveProductBill.setCreateBy("ERP");
        receiveProductBillService.insertReceiveProductBill(receiveProductBill);
    }

    /**
     * 调拨入库单
     *
     * @param instockCreateVo 入库创建
     */
    private void handleAdjustInBill(InstockCreateVo instockCreateVo) {
        //调拨单⼊库单 DITRS 4
        //TODO 调用调拨入库单创建接口
        AdjustInBill bill = adjustInBillService.selectAdjustInBillByNo(instockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", instockCreateVo.getBizNo());
            return;
        }
        AdjustInBill adjustInBill = new AdjustInBill();
        adjustInBill.setNo(instockCreateVo.getBizNo());
        adjustInBill.setStockCode(instockCreateVo.getStockCode());
        adjustInBill.setOwner(instockCreateVo.getOwner());
        adjustInBill.setStockStatus(instockCreateVo.getStockStatus().toString());
        adjustInBill.setArrivalDate(DateUtils.parseDate(instockCreateVo.getArrivalDate()));
        adjustInBill.setShortMatch(instockCreateVo.getShortMatch().toString());
        adjustInBill.setRemark(instockCreateVo.getRemark());
        adjustInBill.setSplit(instockCreateVo.getIsSplit().toString());
        adjustInBill.setStatus(InOrderStatusEnum.NEW.getCode());
        adjustInBill.setCheckTotalQty(0l);
        Long total = 0l;
        //子表入库
        for (GoodsVo detail : instockCreateVo.getGoodDetails()) {
            AdjustInBillDetail adjustInBillDetail = new AdjustInBillDetail();
            adjustInBillDetail.setBillNo(instockCreateVo.getBizNo());
            adjustInBillDetail.setProductNo(detail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(detail.getCode());
            if (product != null) {
                adjustInBillDetail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(detail.getNum());
            adjustInBillDetail.setQty(num);
            adjustInBillDetail.setReceivedQty(0l);
            adjustInBillDetail.setProductUnit(detail.getUnit());
            adjustInBillDetail.setBatchNo(detail.getBatchNo());
            adjustInBillDetail.setCreateBy("ERP");
            total += num;
            adjustInBillDetailService.insertAdjustInBillDetail(adjustInBillDetail);
        }
        adjustInBill.setTotalQty(total);
        adjustInBill.setCreateBy("ERP");
        adjustInBillService.insertAdjustInBill(adjustInBill);
    }

    /**
     * 入库调整单
     *
     * @param instockCreateVo 入库调整单创建
     */
    private void handleModulationInBill(InstockCreateVo instockCreateVo) {
        //入库调整单
        //TODO 调用入库调整单创建接口
        ModulationInBill bill = modulationInBillService.selectModulationInBillByNo(instockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", instockCreateVo.getBizNo());
            return;
        }
        ModulationInBill modulationInBill = new ModulationInBill();
        modulationInBill.setBizNo(instockCreateVo.getBizNo());
        modulationInBill.setStockCode(instockCreateVo.getStockCode());
        modulationInBill.setOwner(instockCreateVo.getOwner());
        modulationInBill.setStockStatus(instockCreateVo.getStockStatus().toString());
        modulationInBill.setRemark(instockCreateVo.getRemark());
        modulationInBill.setStatus(InOrderStatusEnum.NEW.getCode());
        modulationInBill.setCheckTotalQty(0L);
        Long total = 0l;
        //子表入库
        for (GoodsVo goodDetail : instockCreateVo.getGoodDetails()) {
            ModulationInBillDetail detail = new ModulationInBillDetail();
            detail.setBizNo(instockCreateVo.getBizNo());
            detail.setProductNo(goodDetail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(goodDetail.getCode());
            if (product != null) {
                detail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(goodDetail.getNum());
            detail.setQty(num);
            detail.setReceivedQty(0L);
            detail.setProductUnit(goodDetail.getUnit());
            detail.setBatchNo(goodDetail.getBatchNo());
            detail.setCreateBy("ERP");
            total += num;
            modulationInBillDetailService.insertModulationInBillDetail(detail);
        }
        modulationInBill.setCreateBy("ERP");
        modulationInBill.setTotalQty(total);
        modulationInBillService.insertModulationInBill(modulationInBill);

    }

    /**
     * 持久化需求单的topic
     */
    public static final String TOPIC = "global-tms-requirement_order-create";

    /**
     * 需求单管理新增
     *
     * @param request 请求参数
     * @return 新增结果
     */
    @ApiOperation(value = "测试加密")
    @ApiInterfaceLog(title = "测试加密")
    @PostMapping(value = "/testEncrypt")
    public String add(HttpServletRequest request) {
//        String requirementOrderReqJsonStr = getCommonReq(request).getData();
        log.info("requirementOrderReqJsonStr解析后内容为：{}", request.getParameter("cid"));
        try {
            return buildResult(true, null);
        } catch (Exception e) {
            log.error("创建需求单异常,msg:{}", e.getMessage(), e);
            return buildResult(false, e.getMessage());
        }
    }

    /**
     * 生成返回结果
     *
     * @param hasSuccess
     * @return
     */
    private static String buildResult(boolean hasSuccess, String defaultMsg) {
        ApiResult<ResultDTO<AjaxResult>> result = new ApiResult<>();
        ResultDTO<AjaxResult> resultDTO = new ResultDTO<>();
        AjaxResult ajaxResult = new AjaxResult();
        if (hasSuccess) {
            resultDTO.setStatus("success");
            ajaxResult.success(defaultMsg);
        } else {
            resultDTO.setStatus("fail");
            ajaxResult.error(defaultMsg);
        }
        result.setContent(resultDTO);
        resultDTO.setData(ajaxResult);

        return AesCryptorUtils.encrypt(JSONUtil.toJsonStr(result), AesCryptorUtils.SECURITY_KEY);
    }
}
